package com.rykj.energy.task.api.service.impl;

import com.alibaba.fastjson.JSON;
import com.rykj.energy.common.dto.CameraDto;
import com.rykj.energy.common.dto.TaskCameraRelationDto;
import com.rykj.energy.common.enums.TaskState;
import com.rykj.energy.common.utils.*;
import com.rykj.energy.database.mapper.CameraMapper;
import com.rykj.energy.database.mapper.TaskCameraRelationMapper;
import com.rykj.energy.database.mapper.TaskInfoMapper;
import com.rykj.energy.database.pojo.BasicCamera;
import com.rykj.energy.database.pojo.TaskCameraRelation;
import com.rykj.energy.database.pojo.TaskInfo;
import com.rykj.energy.database.pojo.vo.TaskInfoVo;
import com.rykj.energy.database.service.ICameraService;
import com.rykj.energy.database.service.ITaskCameraRelationService;
import com.rykj.energy.database.service.ITaskInfoService;
import com.rykj.energy.task.api.service.ITaskService;
import com.rykj.energy.task.manage.TaskManageFactorySchedule;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

@Service("taskService")
@Slf4j
public class TaskServiceImpl implements ITaskService {

    @Autowired
    private TaskInfoMapper taskInfoMapper;

    @Autowired
    private TaskCameraRelationMapper taskCameraRelationMapper;

    @Autowired
    private ITaskCameraRelationService taskCameraRelationService;

    @Autowired
    private TaskManageFactorySchedule taskManageFactory;

    @Autowired
    private ITaskInfoService taskInfoService;

    @Autowired
    private ICameraService cameraService;

    @Autowired
    private CameraMapper cameraMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveBatchTaskForTask(TaskInfoVo taskInfo) throws Exception {

        boolean isU = false; //任务全局参数是否发生变化,如果发生变化，所有运行中任务需重启
        boolean isExec = false; //任务的全局执行计划是否发生变化
        TaskInfo task = taskInfoMapper.findInfoByCode(taskInfo.getTaskCode());
        if(task != null){
            //任务参数发生变化，需全部更新任务
            if(taskInfo.getBusinessContent()!=null&&task.getBusinessContent()!=null
                    &&!taskInfo.getBusinessContent().equals(task.getBusinessContent())){
                isU = true;
            }
            if(taskInfo.getExecPlan()!=null&&task.getExecPlan()!=null
                    &&!taskInfo.getExecPlan().equals(task.getExecPlan())){
                isExec = true;
            }
        } else {
            task = new TaskInfo();
        }

        //保存/更新任务基本信息
        BeanUtils.copyProperties(taskInfo,task);
        taskInfoService.saveOrUpdateTask(task);

        //任务处理(该停的停，该更新的更新)
        List<TaskCameraRelationDto> taskCameraRelations = taskCameraRelationMapper.findUnCloseByTaskId(taskInfo.getId(),"close");
        List<TaskCameraRelationDto> waitCameraRelations = taskInfo.getTaskCameras(); //等待运行的任务

        for(TaskCameraRelationDto relation : waitCameraRelations){
            if(StringUtils.isBlank(relation.getExecPlan())){
                //如果摄像头任务未单独定义执行计划，以全局执行计划为准
                relation.setExecPlan(taskInfo.getExecPlan());
            }

        }
        handleCameraTask(taskCameraRelations,waitCameraRelations,isU); //对比处理页面提交的任务
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveBatchTaskForCamera(int cameraId, List<TaskCameraRelationDto> waitTaskCamera) throws Exception {

        //任务处理(该停的停，该更新的更新)
        List<TaskCameraRelationDto> taskCamera = taskCameraRelationMapper.findUnCloseByCameraId(cameraId);
        if(waitTaskCamera!=null){
            BasicCamera camera = cameraService.findById(cameraId);
            for(TaskCameraRelationDto relation : waitTaskCamera){
                TaskInfo taskInfo = taskInfoMapper.findInfoByCode(relation.getTaskCode());
                if(taskInfo == null){
                    throw new Exception("任务不存在,请检查");
                }
                //补全摄像头冗余信息
                relation.setPresetId(null);//预置位暂时设置null
                relation.setCameraId(cameraId);
                relation.setCameraNo(camera.getCamNo());
                relation.setStatus(TaskState.run.getCode());
                relation.setCreateTime(new Date());
                relation.setTaskType(taskInfo.getTaskType());
                relation.setTaskId(taskInfo.getId());
                relation.setOrgId(camera.getOrgId());
                //如果摄像头任务未单独定义执行计划，以全局执行计划为准
                if(StringUtils.isBlank(relation.getExecPlan())){
                    relation.setExecPlan(taskInfo.getExecPlan());
                }
            }
        }

        handleCameraTask(taskCamera,waitTaskCamera,false); //对比处理页面提交的任务
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveBatchTaskForCamera(List<CameraDto> taskInfos) throws Exception {

        if(taskInfos!=null){
            for(CameraDto cameraDto : taskInfos){
                String cameraNo = cameraDto.getCameraNo();
                if(StringUtils.isBlank(cameraNo)){
                    throw new Exception("摄像头编号不能为空！");
                }
                if(cameraDto.getChannelIndex()!=null&&cameraDto.getChannelIndex()==2){
                    cameraNo = cameraNo + "-" + 2;
                }

				//通过摄像头编号获取摄像头信息
                BasicCamera camera = cameraService.findInfoByCameraNo(cameraNo);
                //任务处理(该停的停，该更新的更新)
                int cameraId = camera.getId();
                //找出该摄像头下等待启停的任务
                saveBatchTaskForCamera(cameraId,cameraDto.getTaskCameras());
            }
        }

    }

    @Override
    public TaskInfoVo getTaskCameraByCode(String code) throws Exception {
        TaskInfo task = taskInfoMapper.findInfoByCode(code);
        TaskInfoVo taskInfoVo = new TaskInfoVo();
        BeanUtils.copyProperties(task,taskInfoVo);
        List<TaskCameraRelationDto> taskCameraRels=taskCameraRelationMapper.findUnCloseByTaskId(task.getId(),null);
        taskInfoVo.setTaskCameras(taskCameraRels);
        return taskInfoVo;
    }

    @Override
    public List<TaskCameraRelationDto> getTaskCameraByCameraId(String cameraId, String tasksStatus) {
        return taskCameraRelationMapper.getAllByCameraIdAndStatus(cameraId,tasksStatus);
    }

    /**
     * 任务启停操作时，对比处理任务
     * 该停止删掉的任务停止删除、新增/更新任务
     * @param taskCameras 历史已经提交的任务
     * @param waitTaskCamera 页面操作，等待提交运行的任务
     * @param isU 是否全量更新
     * @throws Exception
     */
    public void handleCameraTask(List<TaskCameraRelationDto> taskCameras, List<TaskCameraRelationDto> waitTaskCamera, boolean isU) throws Exception {
        //任务删除/停止
        List<TaskCameraRelationDto> delC = getDelTaskCamera(taskCameras,waitTaskCamera);
        if(delC != null&&delC.size()>0){
            List<Integer> delIds = new ArrayList<>();
            delC.forEach(r->delIds.add(r.getId()));
            taskCameraRelationMapper.updateTaskClose(delIds);

            taskManageFactory.stopTask(delC); //停止任务
            log.info("批量删除任务:{}",delIds);
        }

        if(waitTaskCamera!=null&&waitTaskCamera.size()>0){
            //新增任务
            List<TaskCameraRelationDto> addC = getAddTaskCamera(taskCameras,waitTaskCamera);
            if(addC != null&&addC.size()>0){
                for(TaskCameraRelationDto relation : addC){
                    //如果任务关联关系已经存在，则修改，反之新增
                    TaskCameraRelation re = taskCameraRelationMapper.findByTaskIdAndCameraIdAndPreseId(relation.getTaskId(),relation.getCameraId(),relation.getPresetId());
                    if(re!=null){
                        taskCameraRelationService.updateTaskCamera(relation);
                    }else{
                        taskCameraRelationService.save(relation);
                    }
                }

                taskManageFactory.startTask(addC);
                log.info("批量增加任务:{}", JsonUtil.beanToString(addC));
            }

            //更新任务
            List<TaskCameraRelationDto> updateC = getUpdateTaskCamera(taskCameras,waitTaskCamera,isU);
            if(updateC != null&&updateC.size()>0){
                for(TaskCameraRelationDto relation : updateC){
                    taskCameraRelationService.updateTaskCamera(relation);
                }
                taskManageFactory.updateTask(updateC);
                log.info("批量更新任务:{}", JsonUtil.beanToString(updateC));
            }
        }
    }
    /**
     * 对比找出需要删除的任务
     * @param all
     * @param wait
     * @return
     */
    private static List<TaskCameraRelationDto> getDelTaskCamera(List<TaskCameraRelationDto> all,List<TaskCameraRelationDto> wait){

        if(all==null){
            return null;
        }else if(wait==null){
            return all;
        }else{
            List<TaskCameraRelationDto> delTaskCameras = new ArrayList<>();
            delTaskCameras.addAll(all);
            delTaskCameras.removeAll(wait);
            return delTaskCameras;
        }
    }

    /**
     * 对比找出新增加的任务
     * @param all
     * @param wait
     * @return
     */
    private static List<TaskCameraRelationDto> getAddTaskCamera(List<TaskCameraRelationDto> all,List<TaskCameraRelationDto> wait){

        if(all==null){
            return wait;
        }else if(wait==null){
            return null;
        }else{
            List<TaskCameraRelationDto> addTaskCameras = new ArrayList<>();
            addTaskCameras.addAll(wait);
            addTaskCameras.removeAll(all);
            return addTaskCameras;
        }
    }

    /**
     * 对比找出需更新的任务---任务参数发生变化
     * @param all
     * @param wait
     * @param isU 是否整体更新
     * @return
     */
    private static List<TaskCameraRelationDto> getUpdateTaskCamera(List<TaskCameraRelationDto> all,List<TaskCameraRelationDto> wait,boolean isU){

        if(all==null){
            return null;
        }else if(wait==null){
            return null;
        }else{
            List<TaskCameraRelationDto> updateTaskCameras = new ArrayList<>();
            for(TaskCameraRelationDto relation : wait){
                if(all.contains(relation)){
                    if(isU){ //已经开启的任务全部更新
                        updateTaskCameras.add(relation);
                    }else{
                        //对比参数是否有变化
                        int index = all.indexOf(relation);
                        TaskCameraRelationDto old = all.get(index);
                        String newB = relation.getBusinessContent()==null?"":relation.getBusinessContent();
                        String oldB = old.getBusinessContent()==null?"":old.getBusinessContent();
                        String newE = relation.getExecPlan()==null?"":relation.getExecPlan();
                        String oldE = old.getExecPlan()==null?"":old.getExecPlan();
                        if(!newB.equals(oldB)||!newE.equals(oldE)){
                            updateTaskCameras.add(relation);
                        }
                    }
                }
            }
            return updateTaskCameras;
        }
    }
}
